#ifndef _HASHMAP_H
#define _HASHMAP_H

#include <stdbool.h>
#include <stddef.h>

typedef struct hashmap_t hashmap_t;
typedef struct entry_t entry_t;

typedef unsigned (*Hashcode)(hashmap_t *map, void *key);
typedef bool (*Equals)(void *k1, void *k2);
typedef void (*Put)(hashmap_t *map, void *key, void *value);
typedef void *(*Get)(hashmap_t *map, void *key);
typedef bool (*Remove)(hashmap_t *map, void *key);
typedef void (*Clear)(hashmap_t *map);
typedef bool (*Exists)(hashmap_t *map, void *key);

struct entry_t {
  void *key;
  void *value;
  struct entry_t *next;
};

struct hashmap_t {
  size_t size;
  size_t cap;
  entry_t *entry_list;

  Hashcode hashcode;
  Equals equals;
  Put put;
  Get get;
  Remove remove;
  Clear clear;
  Exists exists;
  bool auto_assign;
};

hashmap_t *create_hashmap(Hashcode hashcode, Equals equals);
void free_hashmap(hashmap_t **mapptr);

unsigned str_hashcode(hashmap_t *map, void *key);

typedef struct {
  entry_t *entry;
  int count;
  int hashcode;
  hashmap_t *map;
} hashmap_iter_t;

hashmap_iter_t *create_hashmap_iter(hashmap_t *map);
bool has_next_hashmap_iter(hashmap_iter_t *iterator);
hashmap_iter_t *next_hashamp_iter(hashmap_iter_t *iterator);
void free_hashmap_iter(hashmap_iter_t **iterator);

#endif
